{% extends "base.html" %}

{% block title %}测试用例管理 - UI自动化测试平台{% endblock %}

{% block content %}
<div class="row">
    <div class="col-md-12">
        <div class="d-flex justify-content-between align-items-center mb-3">
            <h2>测试用例管理</h2>
            <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#testCaseModal" id="addTestCaseBtn">
                <i class="bi bi-plus"></i> 新建测试用例
            </button>
        </div>
        
        <!-- 搜索控件区域 -->
        <div class="row mb-3">
            <div class="col-md-4">
                <label class="form-label">优先级筛选</label>
                <div class="priority-filter-container position-relative">
                    <!-- 隐藏的多选下拉框 -->
                    <select class="form-select d-none" id="priorityFilter" multiple>
                        <option value="">全部</option>
                        <option value="P1">P1（最高）</option>
                        <option value="P2">P2（重要）</option>
                        <option value="P3">P3（一般）</option>
                        <option value="P4">P4（最低）</option>
                    </select>
                    
                    <!-- 显示选中项的容器 -->
                    <div class="selected-priorities-container border rounded p-2" style="min-height: 38px; cursor: pointer;">
                        <div class="d-flex flex-wrap align-items-center gap-2" id="selectedPriorities">
                            <span class="text-muted">全部</span>
                        </div>
                    </div>
                    
                    <!-- 下拉选项 -->
                    <div class="priority-dropdown-options border rounded d-none" id="priorityOptions" style="position: absolute; top: 100%; left: 0; right: 0; background: white; z-index: 1000; box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1); max-height: 200px; overflow-y: auto;">
                        <div class="p-2">
                            <div class="form-check" data-value="">
                                <input class="form-check-input" type="checkbox" id="priorityAll" value="">
                                <label class="form-check-label" for="priorityAll">全部</label>
                            </div>
                            <div class="form-check" data-value="P1">
                                <input class="form-check-input" type="checkbox" id="priorityP1" value="P1">
                                <label class="form-check-label" for="priorityP1">P1（最高）</label>
                            </div>
                            <div class="form-check" data-value="P2">
                                <input class="form-check-input" type="checkbox" id="priorityP2" value="P2">
                                <label class="form-check-label" for="priorityP2">P2（重要）</label>
                            </div>
                            <div class="form-check" data-value="P3">
                                <input class="form-check-input" type="checkbox" id="priorityP3" value="P3">
                                <label class="form-check-label" for="priorityP3">P3（一般）</label>
                            </div>
                            <div class="form-check" data-value="P4">
                                <input class="form-check-input" type="checkbox" id="priorityP4" value="P4">
                                <label class="form-check-label" for="priorityP4">P4（最低）</label>
                            </div>
                        </div>
                    </div>
                </div>
                <div class="form-text">点击选择优先级，可多选</div>
            </div>
            <div class="col-md-4">
                <label for="dependencyFilter" class="form-label">依赖状态筛选</label>
                <select class="form-select" id="dependencyFilter">
                    <option value="">全部</option>
                    <option value="yes">是</option>
                    <option value="no">否</option>
                </select>
            </div>
        </div>
        
        <div class="card">
            <div class="card-body">
                <div class="table-responsive">
                    <table class="table table-striped table-hover" id="testCasesTable">
                        <thead>
                            <tr>
                                <th>序号</th>
                                <th>名称</th>
                                <th>优先级</th>
                                <th>被引用次数</th>
                                <th>依赖状态</th>
                                <th>创建时间</th>
                                <th>操作</th>
                            </tr>
                        </thead>
                        <tbody>
                            <!-- 数据将通过JavaScript动态加载 -->
                        </tbody>
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>

<!-- 测试用例模态框 -->
<div class="modal fade" id="testCaseModal" tabindex="-1">
    <div class="modal-dialog modal-lg">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="testCaseModalLabel">测试用例</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <form id="testCaseForm">
                    <input type="hidden" id="testCaseId">
                    <div class="mb-3">
                        <label for="testCaseName" class="form-label">名称 *</label>
                        <input type="text" class="form-control" id="testCaseName" required>
                    </div>
                    <div class="mb-3">
                        <label for="testCasePriority" class="form-label">优先级 *</label>
                        <select class="form-select" id="testCasePriority" required>
                            <option value="P1">P1（最高）</option>
                            <option value="P2">P2（重要）</option>
                            <option value="P3" selected>P3（一般）</option>
                            <option value="P4">P4（最低）</option>
                        </select>
                    </div>
                    <div class="mb-3">
                        <label for="testCaseDescription" class="form-label">描述</label>
                        <textarea class="form-control" id="testCaseDescription" rows="2"></textarea>
                    </div>
                    <div class="mb-3">
                        <label for="testCaseUrl" class="form-label">URL</label>
                        <input type="text" class="form-control" id="testCaseUrl">
                    </div>
                    <div class="mb-3">
                        <label class="form-label">前置条件</label>
                        <div class="precondition-container">
                            <!-- 已选择的测试用例将显示在这里，支持拖动排序 -->
                            <div class="selected-preconditions mb-2" id="selectedPreconditions">
                                <!-- 已选择的测试用例会动态添加到这里 -->
                            </div>
                            
                            <!-- 搜索和选择测试用例的下拉菜单 -->
                            <div class="dropdown">
                                <button class="btn btn-outline-secondary dropdown-toggle w-100 d-flex justify-content-between align-items-center" 
                                        type="button" 
                                        id="preconditionDropdown" 
                                        data-bs-toggle="dropdown" 
                                        aria-expanded="false">
                                    <span>选择前置条件</span>
                                    <i class="bi bi-search"></i>
                                </button>
                                <div class="dropdown-menu w-100" aria-labelledby="preconditionDropdown">
                                    <div class="p-2">
                                        <input type="text" class="form-control mb-2" id="preconditionSearch" placeholder="搜索测试用例...">
                                        <div class="precondition-options" id="preconditionOptions" style="max-height: 200px; overflow-y: auto;">
                                            <!-- 测试用例选项将通过JavaScript动态加载 -->
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <input type="hidden" id="preconditionTestCaseIds" value="">
                    </div>
                    <div class="mb-3">
                        <label class="form-label">所属测试套件</label>
                        <div id="testSuitesList">
                            <!-- 测试套件选项将通过JavaScript动态加载 -->
                        </div>
                    </div>
                    <div class="mb-3">
                        <label for="stepsContainer" class="form-label">测试步骤</label>
                        <div id="stepsContainer" class="sortable-steps">
                            <!-- 步骤将在这里动态添加 -->
                        </div>
                        <button type="button" class="btn btn-secondary btn-sm mt-2" id="addStepBtn">
                            <i class="bi bi-plus"></i> 添加步骤
                        </button>
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">取消</button>
                <button type="button" class="btn btn-primary" id="saveTestCaseBtn">保存</button>
            </div>
        </div>
    </div>
</div>

<!-- 执行测试用例模态框 -->
<div class="modal fade" id="executeTestCaseModal" tabindex="-1">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title">执行测试用例</h5>
                <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
            </div>
            <div class="modal-body">
                <div id="executionResult">
                    <!-- 执行结果将在这里显示 -->
                </div>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">关闭</button>
            </div>
        </div>
    </div>
</div>
{% endblock %}

{% block scripts %}
<script src="{{ url_for('static', filename='js/Sortable.min.js') }}"></script>
<script>
    // 当前操作模式：'add' 或 'edit'
    var currentMode = 'add';
    // 存储所有测试用例数据
    var allTestCases = [];
    
    // 页面加载完成后初始化
    $(document).ready(function() {
        // 加载测试用例列表
        loadTestCases();
        
        // 保存测试用例
        $('#saveTestCaseBtn').click(function() {
            saveTestCase();
        });
        
        // 添加步骤
        $('#addStepBtn').click(function() {
            addStep();
        });
        
        // 新建测试用例按钮点击事件
        $('#addTestCaseBtn').click(function() {
            currentMode = 'add';
            resetForm();
        });
        
        // 页面显示时根据操作模式决定是否重置表单
        $('#testCaseModal').on('show.bs.modal', function (event) {
            // 如果是新建模式，则重置表单
            if (currentMode === 'add') {
                resetForm();
            }
        });
        
        // 前置条件搜索功能
        $(document).on('input', '#preconditionSearch', function() {
            var searchTerm = $(this).val().toLowerCase();
            $('#preconditionOptions .dropdown-item').each(function() {
                var text = $(this).text().toLowerCase();
                if (text.includes(searchTerm)) {
                    $(this).show();
                } else {
                    $(this).hide();
                }
            });
        });
        
        // 初始化拖动排序
        initPreconditionSortable();
        initStepsSortable();
        
        // 加载前置条件测试用例选项（初始加载不需要过滤）
        loadPreconditionTestCases();  
        
        // 初始化优先级筛选组件
        initPriorityFilter();
        
        // 添加搜索事件监听器
        $('#dependencyFilter').on('change', function() {
            var filteredTestCases = filterTestCases(allTestCases);
            displayTestCases(filteredTestCases);
        });
    });
    
    // 初始化优先级筛选组件
    function initPriorityFilter() {
        // 设置默认选中"全部"
        $('#priorityAll').prop('checked', true);
        updatePriorityFilter();
        
        // 点击显示选中项容器时，显示下拉选项
        $('.selected-priorities-container').on('click', function(e) {
            if (!$(e.target).hasClass('remove-tag')) {
                $('#priorityOptions').removeClass('d-none');
            }
        });
        
        // 点击其他地方时隐藏下拉选项
        $(document).on('click', function(e) {
            if (!$(e.target).closest('.priority-filter-container').length) {
                $('#priorityOptions').addClass('d-none');
            }
        });
        
        // 处理复选框变化
        $('#priorityOptions input[type="checkbox"]').on('change', function() {
            // 获取当前选中的复选框
            var currentCheckbox = $(this);
            var currentValue = currentCheckbox.val();
            
            // 如果选中的是"全部"选项
            if (currentValue === "" && currentCheckbox.is(':checked')) {
                // 取消其他所有选项
                $('#priorityOptions input[type="checkbox"]').not(currentCheckbox).prop('checked', false);
            } 
            // 如果选中的是具体优先级选项
            else if (currentValue !== "" && currentCheckbox.is(':checked')) {
                // 取消"全部"选项
                $('#priorityAll').prop('checked', false);
            }
            
            updatePriorityFilter();
        });
    }
    
    // 更新优先级筛选
    function updatePriorityFilter() {
        // 获取选中的值
        var selectedValues = [];
        $('#priorityOptions input[type="checkbox"]:checked').each(function() {
            selectedValues.push($(this).val());
        });
        
        // 如果没有选中任何项，默认选中"全部"
        if (selectedValues.length === 0) {
            $('#priorityAll').prop('checked', true);
            selectedValues = [""];
        }
        
        // 更新隐藏的select元素
        $('#priorityFilter').val(selectedValues);
        
        // 更新显示的标签
        updatePriorityTags(selectedValues);
        
        // 隐藏下拉选项
        $('#priorityOptions').addClass('d-none');
        
        // 应用筛选
        var filteredTestCases = filterTestCases(allTestCases);
        displayTestCases(filteredTestCases);
    }
    
    // 更新优先级标签显示
    function updatePriorityTags(selectedValues) {
        var container = $('#selectedPriorities');
        container.empty();
        
        if (selectedValues.length === 0 || (selectedValues.length === 1 && selectedValues[0] === "")) {
            container.append('<span class="text-muted">全部</span>');
            return;
        }
        
        // 映射优先级值到显示文本
        var priorityMap = {
            'P1': 'P1（最高）',
            'P2': 'P2（重要）',
            'P3': 'P3（一般）',
            'P4': 'P4（最低）'
        };
        
        // 添加选中的标签
        selectedValues.forEach(function(value) {
            if (value !== "") {
                var tagHtml = `
                    <span class="badge bg-primary d-flex align-items-center" data-value="${value}">
                        ${priorityMap[value] || value}
                        <button type="button" class="btn-close btn-close-white ms-1 remove-tag" aria-label="Remove" data-value="${value}"></button>
                    </span>
                `;
                container.append(tagHtml);
            }
        });
        
        // 绑定删除标签事件
        $('.remove-tag').on('click', function(e) {
            e.stopPropagation();
            var valueToRemove = $(this).data('value');
            // 取消对应的复选框
            $('#priorityOptions input[value="' + valueToRemove + '"]').prop('checked', false);
            
            // 如果取消的是最后一个选项，选中"全部"
            var remainingChecked = $('#priorityOptions input[type="checkbox"]:checked');
            if (remainingChecked.length === 0) {
                $('#priorityAll').prop('checked', true);
            }
            
            // 更新筛选
            updatePriorityFilter();
        });
    }
    
    // 初始化前置条件拖动排序
    function initPreconditionSortable() {
        var el = document.getElementById('selectedPreconditions');
        if (el) {
            new Sortable(el, {
                animation: 150,
                ghostClass: 'sortable-ghost',
                chosenClass: 'sortable-chosen',
                dragClass: 'sortable-drag',
                onEnd: function(evt) {
                    updatePreconditionIds();
                }
            });
        }
    }
    
    // 初始化测试步骤拖动排序
    function initStepsSortable() {
        var el = document.getElementById('stepsContainer');
        if (el) {
            new Sortable(el, {
                animation: 150,
                handle: '.card-header',
                ghostClass: 'sortable-ghost',
                chosenClass: 'sortable-chosen',
                dragClass: 'sortable-drag',
                onEnd: function(evt) {
                    // 拖拽结束后更新步骤编号
                    updateStepNumbers();
                }
            });
        }
    }
    
    // 更新前置条件ID列表
    function updatePreconditionIds() {
        var ids = [];
        $('#selectedPreconditions .precondition-item').each(function() {
            ids.push($(this).data('id'));
        });
        $('#preconditionTestCaseIds').val(ids.join(','));
    }
    
    // 添加前置条件
    function addPrecondition(id, name) {
        // 检查是否已添加
        if ($('#selectedPreconditions .precondition-item[data-id="' + id + '"]').length > 0) {
            return;
        }
        
        var preconditionHtml = `
            <div class="precondition-item d-flex align-items-center bg-light p-2 mb-1 rounded" data-id="${id}">
                <i class="bi bi-grip-vertical me-2 handle"></i>
                <span class="flex-grow-1">${name}</span>
                <button type="button" class="btn-close" onclick="removePrecondition(this)"></button>
            </div>
        `;
        $('#selectedPreconditions').append(preconditionHtml);
        updatePreconditionIds();
        
        // 更新选项可见性
        updatePreconditionOptionsVisibility();
    }
    
    // 移除前置条件
    function removePrecondition(button) {
        $(button).closest('.precondition-item').remove();
        updatePreconditionIds();
        
        // 更新选项可见性
        updatePreconditionOptionsVisibility();
    }
    
    // 加载测试用例列表
    function loadTestCases() {
        $.get('/api/testcases')
            .done(function(data) {
                // 保存所有测试用例数据
                allTestCases = data;
                
                // 应用筛选并显示
                var filteredTestCases = filterTestCases(allTestCases);
                displayTestCases(filteredTestCases);
            })
            .fail(function() {
                alert('加载测试用例失败');
            });
    }
    
    // 编辑测试用例函数
    function editTestCase(id) {
        currentMode = 'edit';
        $.get('/api/testcases/' + id)
            .done(function(testCase) {
                // 填充表单字段
                $('#testCaseId').val(testCase.id);
                $('#testCaseName').val(testCase.name);
                $('#testCasePriority').val(testCase.priority);
                $('#testCaseDescription').val(testCase.description);
                $('#testCaseUrl').val(testCase.url);
                
                // 解析并填充前置条件
                $('#selectedPreconditions').empty();
                if (testCase.precondition_test_cases && Array.isArray(testCase.precondition_test_cases)) {
                    testCase.precondition_test_cases.forEach(function(precondition) {
                        addPrecondition(precondition.id, precondition.name);
                    });
                }
                
                // 更新前置条件选项可见性
                updatePreconditionOptionsVisibility();
                
                // 解析并填充步骤
                try {
                    var steps = typeof testCase.steps === 'string' ? JSON.parse(testCase.steps) : testCase.steps;
                    $('#stepsContainer').empty();
                    if (Array.isArray(steps)) {
                        steps.forEach(function(step, index) {
                            addStep();
                            var $lastStepItem = $('.step-item').last();
                            $lastStepItem.find('.step-action').val(step.action || '');
                            $lastStepItem.find('.step-selector-type').val(step.selector_type || '');
                            $lastStepItem.find('.step-selector-value').val(step.selector_value || '');
                            $lastStepItem.find('.step-value').val(step.value || '');
                            
                            // 处理断言类型和范围
                            if (step.action === 'assert_text') {
                                $lastStepItem.find('.step-assert-type').val(step.assert_type || 'contains');
                                $lastStepItem.find('.step-assert-scope').val(step.assert_scope || 'element');
                            }
                            
                            // 处理变量名字段
                            if (step.variable_name) {
                                $lastStepItem.find('.step-variable-name').val(step.variable_name);
                            }
                            
                            // 处理属性名字段
                            if (step.attribute_name !== undefined && step.attribute_name !== null) {
                                $lastStepItem.find('.step-attribute-name').val(step.attribute_name);
                            }
                            
                            // 处理断言变量选择字段
                            if (step.action === 'assert_variable') {
                                $lastStepItem.find('.step-assert-type').val(step.assert_type || 'equals');
                                // 正确处理变量选择的回显
                                var $variableSelect = $lastStepItem.find('.step-variable-select');
                                var $variableName = $lastStepItem.find('.step-variable-name');
                                
                                // 判断是自定义变量还是预定义变量
                                if (step.variable_name && step.variable_select && step.variable_name === step.variable_select) {
                                    // 特殊情况：variable_name和variable_select相同
                                    $variableSelect.val(step.variable_select);
                                    // 不回显自定义变量名，因为这种情况通常表示使用预定义变量
                                    $variableName.val('');
                                } else if (step.variable_name && step.variable_select && step.variable_name !== step.variable_select) {
                                    // 混合情况：有自定义变量名和选择的变量
                                    $variableSelect.val(step.variable_select);
                                    $variableName.val(step.variable_name);
                                } else if (step.variable_name && !step.variable_select) {
                                    // 纯自定义变量情况：只有variable_name，没有variable_select
                                    $variableSelect.val('');
                                    $variableName.val(step.variable_name);
                                } else if (!step.variable_name && step.variable_select) {
                                    // 只选择了预定义变量
                                    $variableSelect.val(step.variable_select);
                                    $variableName.val('');
                                }
                                
                                // 为新创建的步骤绑定事件处理函数
                                $lastStepItem.find('.step-variable-select').change(function() {
                                    handleVariableSelectChange($lastStepItem);
                                });
                                
                                $lastStepItem.find('.step-variable-name').on('input', function() {
                                    handleVariableNameInput($lastStepItem);
                                });
                            }
                            
                            // 应用字段显示逻辑
                            toggleStepFields($lastStepItem);
                            // 应用断言范围字段显示逻辑
                            if (step.action === 'assert_text') {
                                toggleAssertScopeFields($lastStepItem);
                            }
                            
                            // 在字段显示逻辑处理后再次设置各字段的值
                            // 处理变量名字段
                            if (step.variable_name !== undefined && step.variable_name !== null) {
                                $lastStepItem.find('.step-variable-name').val(step.variable_name);
                            }
                            
                            // 处理属性名字段（在字段显示后设置）
                            if (step.attribute_name !== undefined && step.attribute_name !== null) {
                                $lastStepItem.find('.step-attribute-name').val(step.attribute_name);
                            }
                            
                            // 特殊处理断言变量步骤
                            if (step.action === 'assert_variable') {
                                // 重新设置断言变量步骤的字段值
                                var $variableSelect = $lastStepItem.find('.step-variable-select');
                                var $variableName = $lastStepItem.find('.step-variable-name');
                                
                                if (step.variable_name && step.variable_select && step.variable_name === step.variable_select) {
                                    // 特殊情况：variable_name和variable_select相同
                                    $variableSelect.val(step.variable_select);
                                    // 不回显自定义变量名，因为这种情况通常表示使用预定义变量
                                    $variableName.val('');
                                } else if (step.variable_name && step.variable_select && step.variable_name !== step.variable_select) {
                                    // 混合情况
                                    $variableSelect.val(step.variable_select);
                                    $variableName.val(step.variable_name);
                                } else if (step.variable_name && !step.variable_select) {
                                    // 纯自定义变量情况
                                    $variableSelect.val('');
                                    $variableName.val(step.variable_name);
                                } else if (!step.variable_name && step.variable_select) {
                                    // 只选择了预定义变量
                                    $variableSelect.val(step.variable_select);
                                    $variableName.val('');
                                }
                            }
                            
                            // 更新步骤编号
                            $lastStepItem.find('.card-header span').text('步骤 ' + (index + 1));
                        });
                    }
                } catch (e) {
                    console.error('解析测试步骤失败:', e);
                    $('#stepsContainer').empty();
                }
                
                // 加载测试套件选项并选中已关联的
                loadTestSuitesForTestCase(testCase.test_suites || []);
                
                // 设置模态框标题为"编辑测试用例"
                $('#testCaseModalLabel').text('编辑测试用例');
                
                // 加载前置条件选项，过滤掉当前测试用例
                loadPreconditionTestCases(testCase.id);
                
                // 显示模态框
                var modal = new bootstrap.Modal(document.getElementById('testCaseModal'));
                modal.show();
            })
            .fail(function() {
                alert('加载测试用例失败');
            });
    }
    
    // 重置表单
    function resetForm() {
        $('#testCaseId').val('');
        $('#testCaseName').val('');
        $('#testCasePriority').val('P3');
        $('#testCaseDescription').val('');
        $('#testCaseUrl').val('');
        $('#testCaseExpectedResult').val('');
        $('#stepsContainer').empty();
        // 重置前置条件
        $('#selectedPreconditions').empty();
        $('#preconditionSearch').val('');
        $('#preconditionTestCaseIds').val('');
        // 重置测试套件选择
        $('.testSuiteCheckbox').prop('checked', false);
        $('#testCaseModalLabel').text('新建测试用例');
        
        // 重新初始化步骤拖动排序
        initStepsSortable();
        
        // 加载前置条件选项（新建测试用例不需要过滤）
        loadPreconditionTestCases();
        
        // 更新前置条件选项可见性
        updatePreconditionOptionsVisibility();
    }
    

    function loadPreconditionTestCases(currentTestCaseId) {
        $.get('/api/testcases')
            .done(function(data) {
                var container = $('#preconditionOptions');
                container.empty();
                
                data.forEach(function(testCase) {
                    // 过滤掉当前测试用例自身
                    if (currentTestCaseId && testCase.id === currentTestCaseId) {
                        return;
                    }
                    
                    var option = $(`<button class="dropdown-item" type="button" data-id="${testCase.id}">${testCase.name}</button>`);
                    option.click(function() {
                        addPrecondition($(this).data('id'), $(this).text());
                    });
                    container.append(option);
                });
                
                // 检查已选择的前置条件并隐藏对应选项
                updatePreconditionOptionsVisibility();
            })
            .fail(function() {
                console.error('加载前置条件测试用例失败');
            });
    }
    

    function saveTestCase() {
        // 获取前置条件ID列表
        var preconditionIds = $('#preconditionTestCaseIds').val();
        var preconditionIdArray = preconditionIds ? preconditionIds.split(',').map(id => parseInt(id)) : [];
        
        // 获取所有选中的测试套件ID
        var testSuiteIds = $('.testSuiteCheckbox:checked').map(function() {
            return parseInt($(this).val(), 10);
        }).get();
        
        var formData = {
            name: $('#testCaseName').val(),
            priority: $('#testCasePriority').val(),
            description: $('#testCaseDescription').val(),
            url: $('#testCaseUrl').val(),
            steps: getStepsData(),
            precondition_test_case_ids: preconditionIdArray,
            test_suite_ids: testSuiteIds
        };
        
        if (currentMode === 'edit') {
            formData.id = $('#testCaseId').val();
        }
        
        $.ajax({
            url: currentMode === 'add' ? '/api/testcases' : `/api/testcases/${formData.id}`,
            method: currentMode === 'add' ? 'POST' : 'PUT',
            data: JSON.stringify(formData),
            contentType: 'application/json'
        })
        .done(function(response) {
            showToast('保存成功');
            $('#testCaseModal').modal('hide');
            loadTestCases();  // 刷新测试用例列表
        })
        .fail(function(xhr, status, error) {
            showToast(`保存失败: ${xhr.responseJSON ? xhr.responseJSON.error : error}`, 'error');
        });
    }
    
    // 删除测试用例
    function deleteTestCase(id) {
        // 直接删除，无需确认
        $.ajax({
            url: '/api/testcases/' + id,
            method: 'DELETE'
        })
        .done(function() {
            loadTestCases();
            showToast('删除成功');
        })
        .fail(function() {
            showToast('删除失败', 'error');
        });
    }
    
    // 复制测试用例
    function copyTestCase(id) {
        // 先获取要复制的测试用例详情
        $.get('/api/testcases/' + id)
            .done(function(testCase) {
                // 准备新测试用例数据，名称加上" - 副本"后缀
                var newTestCase = {
                    name: testCase.name + ' - 副本',
                    description: testCase.description,
                    url: testCase.url,
                    steps: typeof testCase.steps === 'string' ? JSON.parse(testCase.steps) : testCase.steps,
                    test_suite_ids: testCase.test_suites ? testCase.test_suites.map(suite => suite.id) : []
                };
                
                // 如果steps还是字符串（双重编码），再次解析
                if (typeof newTestCase.steps === 'string') {
                    newTestCase.steps = JSON.parse(newTestCase.steps);
                }
                
                // 创建新的测试用例
                $.ajax({
                    url: '/api/testcases',
                    method: 'POST',
                    contentType: 'application/json',
                    data: JSON.stringify(newTestCase)
                })
                .done(function() {
                    loadTestCases();
                    showToast('复制成功');
                })
                .fail(function() {
                    showToast('复制失败', 'error');
                });
            })
            .fail(function() {
                showToast('获取测试用例失败', 'error');
            });
    }
    
    // 执行测试用例
    function executeTestCase(id) {
        // 显示执行结果区域
        $('#executionResult').html('<div class="text-center"><div class="spinner-border" role="status"></div><p>执行中...</p></div>');
        var modal = new bootstrap.Modal(document.getElementById('executeTestCaseModal'));
        modal.show();
        
        // 获取选中的浏览器
        var selectedBrowser = localStorage.getItem('selectedBrowser') || 'edge';
        
        $.ajax({
            url: '/api/testcases/' + id + '/execute',
            method: 'POST',
            contentType: 'application/json',
            data: JSON.stringify({browser: selectedBrowser})
        })
            .done(function(result) {
                var statusClass = result.status === 'PASS' ? 'success' : result.status === 'FAIL' ? 'danger' : 'warning';
                var resultHtml = `
                    <div class="alert alert-${statusClass}" role="alert">
                        <h5>执行结果: ${result.status}</h5>
                        <p>执行时间: ${result.execution_time.toFixed(2)} 秒</p>
                        <p>执行时间: ${formatDate(result.executed_at)}</p>
                        ${result.log ? `<div><label>日志:</label><pre class="log-content bg-light p-2 border" style="white-space: pre-wrap; word-wrap: break-word; max-height: 300px; overflow-y: auto;">${escapeHtml(result.log)}</pre></div>` : ''}
                        ${result.screenshot_path ? `<p>截图: <a href="${result.screenshot_path}" target="_blank">查看截图</a></p>` : ''}
                    </div>
                `;
                $('#executionResult').html(resultHtml);
            })
            .fail(function(xhr) {
                var errorMsg = '执行失败';
                if (xhr.responseJSON && xhr.responseJSON.error) {
                    errorMsg = xhr.responseJSON.error;
                }
                $('#executionResult').html(`<div class="alert alert-danger" role="alert">${errorMsg}</div>`);
            });
    }
    
    // 加载测试套件选项（用于测试用例）
    function loadTestSuitesForTestCase(selectedSuites) {
        $.get('/api/testsuites')
            .done(function(data) {
                var container = $('#testSuitesList');
                container.empty();
                
                if (data.length === 0) {
                    container.html('<p>暂无测试套件</p>');
                    return;
                }
                
                // 创建一个包含已选套件ID的集合，便于快速查找
                var selectedSuiteIds = new Set();
                if (Array.isArray(selectedSuites)) {
                    selectedSuites.forEach(function(suite) {
                        selectedSuiteIds.add(suite.id);
                    });
                }
                
                data.forEach(function(testSuite) {
                    var isChecked = selectedSuiteIds.has(testSuite.id) ? 'checked' : '';
                    var suiteHtml = `
                        <div class="form-check">
                            <input class="form-check-input testSuiteCheckbox" type="checkbox" value="${testSuite.id}" id="testSuite${testSuite.id}" ${isChecked}>
                            <label class="form-check-label" for="testSuite${testSuite.id}">
                                ${testSuite.name}
                            </label>
                        </div>
                    `;
                    container.append(suiteHtml);
                });
            })
            .fail(function() {
                container.html('<p>加载测试套件失败</p>');
            });
    }
    
    // 添加步骤
    function addStep() {
        var stepIndex = $('.step-item').length + 1;
        var stepHtml = `
            <div class="step-item card mb-3">
                <div class="card-header d-flex justify-content-between align-items-center handle">
                    <span>步骤 ${stepIndex}</span>
                    <button type="button" class="btn-close" onclick="removeStep(this)"></button>
                </div>
                <div class="card-body">
                    <div class="row mb-3">
                        <div class="col-md-3">
                            <label class="form-label">操作类型</label>
                            <select class="form-select step-action">
                                <option value="navigate">导航到URL</option>
                                <option value="click">点击元素</option>
                                <option value="input">输入文本</option>
                                <option value="wait">等待(秒)</option>
                                <option value="assert_text">断言文本</option>
                                <option value="assert_variable">断言变量</option>
                                <option value="get_title">获取页面标题</option>
                                <option value="get_text">获取元素文本</option>
                                <option value="get_attribute">获取元素属性</option>
                                <option value="get_window_handles">获取窗口句柄</option>
                                <option value="switch_to_window">切换窗口句柄</option>
                                <option value="close_window">关闭当前窗口</option>
                            </select>
                        </div>
                        <div class="col-md-3 selector-type-col" style="display: none;">
                            <label class="form-label">选择器类型</label>
                            <select class="form-select step-selector-type">
                                <option value="id">ID</option>
                                <option value="name">Name</option>
                                <option value="class">Class</option>
                                <option value="tag">Tag</option>
                                <option value="css">CSS选择器</option>
                                <option value="xpath">XPath</option>
                            </select>
                        </div>
                        <div class="col-md-6 selector-value-col" style="display: none;">
                            <label class="form-label">选择器值</label>
                            <input type="text" class="form-control step-selector-value">
                        </div>
                        <div class="col-md-3 assert-type-col" style="display: none;">
                            <label class="form-label">断言类型</label>
                            <select class="form-select step-assert-type">
                                <option value="contains">包含</option>
                                <option value="equals">等于</option>
                                <option value="not_contains">不包含</option>
                                <option value="not_equals">不等于</option>
                                <option value="starts_with">以...开头</option>
                                <option value="ends_with">以...结尾</option>
                            </select>
                        </div>
                        <div class="col-md-3 assert-scope-col" style="display: none;">
                            <label class="form-label">断言范围</label>
                            <select class="form-select step-assert-scope">
                                <option value="page">整个页面</option>
                                <option value="element">指定元素</option>
                            </select>
                        </div>
                    </div>
                    <div class="row value-row" style="display: none;">
                        <div class="col-md-12">
                            <label class="form-label">值</label>
                            <input type="text" class="form-control step-value">
                        </div>
                    </div>
                </div>
            </div>
        `;
        $('#stepsContainer').append(stepHtml);
        
        // 为新添加的步骤绑定操作类型变化事件
        var $newStepItem = $('.step-item').last();
        $newStepItem.find('.step-action').change(function() {
            toggleStepFields($newStepItem);
        });
        
        // 为断言范围选择绑定事件
        $newStepItem.find('.step-assert-scope').change(function() {
            toggleAssertScopeFields($newStepItem);
        });
        
        // 为断言变量步骤中的变量选择框绑定事件
        $newStepItem.find('.step-variable-select').change(function() {
            handleVariableSelectChange($newStepItem);
        });
        
        // 为自定义变量名输入框绑定事件
        $newStepItem.find('.step-variable-name').on('input', function() {
            handleVariableNameInput($newStepItem);
        });
        
        // 初始化字段显示状态
        toggleStepFields($newStepItem);
    }
    
    // 根据断言范围切换字段显示
    function toggleAssertScopeFields($stepItem) {
        var assertScope = $stepItem.find('.step-assert-scope').val();
        var $selectorTypeCol = $stepItem.find('.selector-type-col');
        var $selectorValueCol = $stepItem.find('.selector-value-col');
        
        if (assertScope === 'page') {
            $selectorTypeCol.hide();
            $selectorValueCol.hide();
        } else {
            $selectorTypeCol.show();
            $selectorValueCol.show();
        }
    }
    
    // 处理断言变量步骤中变量选择变化
    function handleVariableSelectChange($stepItem) {
        var selectedValue = $stepItem.find('.step-variable-select').val();
        // 当选择了一个预定义变量时，清空自定义变量名输入框
        if (selectedValue) {
            $stepItem.find('.step-variable-name').val('');
            // 同时清除user_defined_variable标记
            var stepData = $stepItem.data('step-data') || {};
            stepData.user_defined_variable = false;
            $stepItem.data('step-data', stepData);
        }
    }
    
    // 处理自定义变量名输入
    function handleVariableNameInput($stepItem) {
        var customValue = $stepItem.find('.step-variable-name').val();
        var selectedValue = $stepItem.find('.step-variable-select').val();
        
        // 当输入了自定义变量名且与选择的预定义变量名不同时，清空变量选择下拉框
        if (customValue && selectedValue && customValue !== selectedValue) {
            $stepItem.find('.step-variable-select').val('');
        }
    }
    
    // 根据操作类型切换步骤字段显示
    function toggleStepFields($stepItem) {
        var action = $stepItem.find('.step-action').val();
        var $assertScopeCol = $stepItem.find('.assert-scope-col');
        var $assertTypeCol = $stepItem.find('.assert-type-col');
        var $selectorTypeCol = $stepItem.find('.selector-type-col');
        var $selectorValueCol = $stepItem.find('.selector-value-col');
        var $valueRow = $stepItem.find('.value-row');
        var $attributeNameRow = $stepItem.find('.attribute-name-row'); // 添加属性名行
        var $variableNameRow = $stepItem.find('.variable-name-row'); // 添加变量名行
        var $variableSelectRow = $stepItem.find('.variable-select-row'); // 添加变量选择行
        
        // 默认隐藏所有字段
        $assertScopeCol.hide();
        $assertTypeCol.hide();
        $selectorTypeCol.hide();
        $selectorValueCol.hide();
        $valueRow.hide();
        if ($attributeNameRow) $attributeNameRow.hide(); // 隐藏属性名行
        if ($variableNameRow) $variableNameRow.hide(); // 隐藏变量名行
        if ($variableSelectRow) $variableSelectRow.hide(); // 隐藏变量选择行
        
        // 根据操作类型显示相应字段
        switch(action) {
            case 'navigate':
                $valueRow.show(); // 显示值字段（用于输入URL）
                break;
            case 'click':
                $selectorTypeCol.show();
                $selectorValueCol.show();
                break;
            case 'input':
                $selectorTypeCol.show();
                $selectorValueCol.show();
                $valueRow.show(); // 显示值字段（用于输入文本）
                break;
            case 'wait':
                $valueRow.show(); // 显示值字段（用于输入等待时间）
                break;
            case 'assert_text':
                $assertScopeCol.show(); // 显示断言范围选择
                $assertTypeCol.show(); // 显示断言类型选择
                $valueRow.show(); // 显示值字段（用于输入期望文本）
                // 根据断言范围调整字段显示
                toggleAssertScopeFields($stepItem);
                break;
            case 'assert_variable':
                $assertTypeCol.show(); // 显示断言类型选择

                // 添加变量选择下拉框
                var $variableSelectRow = $stepItem.find('.variable-select-row');
                if (!$variableSelectRow || $variableSelectRow.length === 0) {
                    var variableSelectHtml = `
                        <div class="row variable-select-row">
                            <div class="col-md-12">
                                <label class="form-label">选择变量</label>
                                <select class="form-select step-variable-select">
                                    <option value="">请选择变量</option>
                                    <option value="title">页面标题 (title)</option>
                                    <option value="text">元素文本 (text)</option>
                                    <option value="value">元素属性值 (value)</option>
                                    <option value="href">元素属性值 (href)</option>
                                    <option value="src">元素属性值 (src)</option>
                                    <option value="window_handles">窗口句柄列表 (window_handles)</option>
                                    <option value="current_window_handle">当前窗口句柄 (current_window_handle)</option>
                                </select>
                            </div>
                        </div>
                    `;
                    $assertTypeCol.after(variableSelectHtml);
                } else {
                    $variableSelectRow.show();
                }
                
                // 添加自定义变量名输入框
                var $variableNameRow = $stepItem.find('.variable-name-row');
                if (!$variableNameRow || $variableNameRow.length === 0) {
                    var variableNameHtml = `
                        <div class="row variable-name-row mt-2">
                            <div class="col-md-12">
                                <label class="form-label">自定义变量名</label>
                                <input type="text" class="form-control step-variable-name" placeholder="输入自定义变量名，如果为空则使用上面选择的变量">
                                <div class="form-text">可以输入自定义变量名，或者留空使用上面选择的预定义变量</div>
                            </div>
                        </div>
                    `;
                    $stepItem.find('.variable-select-row').after(variableNameHtml);
                } else {
                    // 更新placeholder文本
                    $variableNameRow.find('.step-variable-name').attr('placeholder', '输入自定义变量名，如果为空则使用上面选择的变量');
                    $variableNameRow.show();
                }

                $valueRow.show(); // 显示值字段（用于输入期望值）
                break;
            case 'get_title':
                // 显示或更新变量名输入框
                if (!$variableNameRow || $variableNameRow.length === 0) {
                    var variableNameHtml = `
                        <div class="row variable-name-row">
                            <div class="col-md-12">
                                <label class="form-label">变量名</label>
                                <input type="text" class="form-control step-variable-name" placeholder="用于存储标题值的变量名，默认为'title'">
                            </div>
                        </div>
                    `;
                    $valueRow.before(variableNameHtml);
                } else {
                    // 更新placeholder文本
                    $variableNameRow.find('.step-variable-name').attr('placeholder', '用于存储标题值的变量名，默认为\'title\'');
                    $variableNameRow.show();
                }
                break;
            case 'get_text':
                $selectorTypeCol.show();
                $selectorValueCol.show();
                // 显示或更新变量名输入框
                if (!$variableNameRow || $variableNameRow.length === 0) {
                    var variableNameHtml = `
                        <div class="row variable-name-row">
                            <div class="col-md-12">
                                <label class="form-label">变量名</label>
                                <input type="text" class="form-control step-variable-name" placeholder="用于存储文本值的变量名，默认为'text'">
                            </div>
                        </div>
                    `;
                    $valueRow.before(variableNameHtml);
                } else {
                    // 更新placeholder文本
                    $variableNameRow.find('.step-variable-name').attr('placeholder', '用于存储文本值的变量名，默认为\'text\'');
                    $variableNameRow.show();
                }
                break;
            case 'get_attribute':
                $selectorTypeCol.show();
                $selectorValueCol.show();
                // 显示属性名输入框
                if (!$attributeNameRow || $attributeNameRow.length === 0) {
                    // 动态创建属性名输入框
                    var attributeNameHtml = `
                        <div class="row attribute-name-row">
                            <div class="col-md-12">
                                <label class="form-label">属性名</label>
                                <input type="text" class="form-control step-attribute-name" placeholder="例如: value, href, src">
                            </div>
                        </div>
                    `;
                    $valueRow.before(attributeNameHtml);
                } else {
                    $attributeNameRow.show();
                }
                // 显示或更新变量名输入框
                if (!$variableNameRow || $variableNameRow.length === 0) {
                    var variableNameHtml = `
                        <div class="row variable-name-row">
                            <div class="col-md-12">
                                <label class="form-label">变量名</label>
                                <input type="text" class="form-control step-variable-name" placeholder="用于存储属性值的变量名，默认为属性名">
                            </div>
                        </div>
                    `;
                    $valueRow.before(variableNameHtml);
                } else {
                    // 更新placeholder文本
                    $variableNameRow.find('.step-variable-name').attr('placeholder', '用于存储属性值的变量名，默认为属性名');
                    $variableNameRow.show();
                }
                break;
            case 'get_window_handles':
                // 显示或更新变量名输入框
                if (!$variableNameRow || $variableNameRow.length === 0) {
                    var variableNameHtml = `
                        <div class="row variable-name-row">
                            <div class="col-md-12">
                                <label class="form-label">变量名</label>
                                <input type="text" class="form-control step-variable-name" placeholder="用于存储句柄列表的变量名，默认为'window_handles'">
                            </div>
                        </div>
                    `;
                    $valueRow.before(variableNameHtml);
                } else {
                    // 更新placeholder文本
                    $variableNameRow.find('.step-variable-name').attr('placeholder', '用于存储句柄列表的变量名，默认为\'window_handles\'');
                    $variableNameRow.show();
                }
                break;
            case 'switch_to_window':
                $valueRow.show(); // 显示值字段（用于输入窗口句柄）
                break;
            case 'close_window':
                // 不需要额外字段
                break;
            default:
                // 默认情况下隐藏所有字段
                $selectorTypeCol.hide();
                $selectorValueCol.hide();
                $valueRow.hide();
        }
    }
    
    // 移除步骤
    function removeStep(button) {
        $(button).closest('.step-item').remove();
        // 更新步骤编号
        updateStepNumbers();
    }
    
    // 更新步骤编号
    function updateStepNumbers() {
        $('.step-item').each(function(index) {
            $(this).find('.card-header span').text('步骤 ' + (index + 1));
        });
    }
    
    // 获取测试步骤数据
    function getStepsData() {
        var steps = [];
        $('.step-item').each(function() {
            var step = {
                action: $(this).find('.step-action').val(),
                selector_type: $(this).find('.step-selector-type').val(),
                selector_value: $(this).find('.step-selector-value').val(),
                value: $(this).find('.step-value').val(),
                assert_type: $(this).find('.step-assert-type').val(),
                assert_scope: $(this).find('.step-assert-scope').val(),
                attribute_name: $(this).find('.step-attribute-name').val(),  // 添加属性名字段
                variable_name: $(this).find('.step-variable-name').val(),  // 添加变量名字段
                variable_select: $(this).find('.step-variable-select').val()  // 添加变量选择字段
            };
            
            // 对于获取类操作，如果变量名为空，则不传递该字段，让后端使用默认值
            if (['get_title', 'get_text', 'get_attribute', 'get_window_handles'].includes(step.action)) {
                if (!step.variable_name) {
                    // 如果变量名为空，删除该字段，让后端使用默认值
                    delete step.variable_name;
                }
            }
            
            // 确保attribute_name字段总是被正确收集
            if (step.action === 'get_attribute') {
                step.attribute_name = step.attribute_name || '';
            }
            
            // 对于assert_variable步骤，正确处理变量名和变量选择的关系
            if (step.action === 'assert_variable') {
                var customVariableName = $(this).find('.step-variable-name').val();
                var selectedVariable = $(this).find('.step-variable-select').val();
                
                
                // 明确区分不同情况
                if (customVariableName && selectedVariable) {
                    // 既有自定义变量名，也有选择的变量 - 保留两者
                    step.variable_name = customVariableName;
                    step.variable_select = selectedVariable;
                } else if (customVariableName && !selectedVariable) {
                    // 只有自定义变量名
                    step.variable_name = customVariableName;
                    step.variable_select = '';
                } else if (!customVariableName && selectedVariable) {
                    // 只选择了预定义变量
                    step.variable_name = selectedVariable;
                    step.variable_select = selectedVariable;
                }
                // 如果两者都为空，则保持原样
            }
            
            steps.push(step);
        });
        return steps;
    }
    
    // 格式化日期
    function formatDate(dateString) {
        if (!dateString) return '';
        var date = new Date(dateString);
        return date.toLocaleString('zh-CN');
    }
    
    // 转义HTML特殊字符
    function escapeHtml(text) {
        var map = {
            '&': '&amp;',
            '<': '&lt;',
            '>': '&gt;',
            '"': '&quot;',
            "'": '&#039;'
        };
        return text.replace(/[&<>"']/g, function(m) { return map[m]; });
    }
    
    // 更新前置条件选项可见性
    function updatePreconditionOptionsVisibility() {
        // 获取已选择的前置条件ID列表
        var selectedIds = [];
        $('#selectedPreconditions .precondition-item').each(function() {
            selectedIds.push(parseInt($(this).data('id')));
        });
        
        // 遍历所有选项
        $('#preconditionOptions .dropdown-item').each(function() {
            var optionId = parseInt($(this).data('id'));
            // 如果选项已选择，则隐藏；否则显示
            if (selectedIds.includes(optionId)) {
                $(this).hide();
            } else {
                $(this).show();
            }
        });
    }
    
    // 过滤测试用例
    function filterTestCases(testCases) {
        // 获取优先级筛选条件
        var selectedPriorities = $('#priorityFilter').val() || [];
        
        // 获取依赖状态筛选条件
        var dependencyFilter = $('#dependencyFilter').val();
        
        // 应用筛选条件
        return testCases.filter(function(testCase) {
            // 优先级筛选（如果选择了"全部"或未选择任何优先级，则显示所有）
            if (selectedPriorities.length > 0 && !selectedPriorities.includes("")) {
                if (!selectedPriorities.includes(testCase.priority)) {
                    return false;
                }
            }
            
            // 依赖状态筛选
            if (dependencyFilter !== '') {
                var hasDependency = testCase.has_dependency ? 'yes' : 'no';
                if (dependencyFilter !== hasDependency) {
                    return false;
                }
            }
            
            return true;
        });
    }
    
    // 显示测试用例列表
    function displayTestCases(testCases) {
        var tbody = $('#testCasesTable tbody');
        tbody.empty();
        
        testCases.forEach(function(testCase, index) {
            var row = `
                <tr>
                    <td>${index + 1}</td>
                    <td>${testCase.name}</td>
                    <td>${testCase.priority}</td>
                    <td>${testCase.referenced_count}</td>
                    <td>${testCase.has_dependency ? '是' : '否'}</td>
                    <td>${formatDate(testCase.created_at)}</td>
                    <td>
                        <button class="btn btn-sm btn-primary" onclick="editTestCase(${testCase.id})">
                            <i class="bi bi-pencil"></i>
                        </button>
                        <button class="btn btn-sm btn-success" onclick="executeTestCase(${testCase.id})">
                            <i class="bi bi-play"></i>
                        </button>
                        <button class="btn btn-sm btn-info" onclick="copyTestCase(${testCase.id})">
                            <i class="bi bi-copy"></i>
                        </button>
                        <button class="btn btn-sm btn-danger" onclick="deleteTestCase(${testCase.id})">
                            <i class="bi bi-trash"></i>
                        </button>
                    </td>
                </tr>
            `;
            tbody.append(row);
        });
    }
</script>
{% endblock %}

<style>
    /* 前置条件下拉框样式优化 */
    .precondition-container .dropdown-toggle {
        background-color: #f5f5f5;
        border-color: #1890ff;
        box-shadow: none;
    }
    
    .precondition-container .dropdown-toggle:hover {
        background-color: #e6f7ff;
    }
    
    .precondition-container .dropdown-toggle:focus {
        border-color: #1890ff;
        box-shadow: 0 0 0 0.2rem rgba(24, 144, 255, 0.25);
    }
    
    .precondition-container .dropdown-toggle::after {
        content: "▼";
        border: none;
        vertical-align: middle;
    }
    
    .precondition-container .dropdown-menu {
        border-color: #1890ff;
        box-shadow: 0 4px 8px rgba(0, 0, 0, 0.1);
        background-color: #e6f7ff; /* 修改：设置下拉菜单背景颜色为浅蓝色 */
    }
    
    .precondition-container .dropdown-item:hover {
        background-color: #d1eaff; /* 修改：设置下拉项悬停时的背景颜色为更深一点的蓝色 */
    }
    
    .precondition-container .selected-preconditions .precondition-item {
        background-color: #f0f8ff;
        border: 1px solid #d1e7ff;
    }
    
    .precondition-container .selected-preconditions .precondition-item:hover {
        background-color: #e6f7ff;
    }
    
    /* 优先级筛选组件样式 */
    .remove-tag {
        font-size: 0.6rem;
        opacity: 0.8;
    }
    
    .remove-tag:hover {
        opacity: 1;
    }
</style>
